/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.animdemo.base;

import com.example.animdemo.SortConstants;
import com.example.animdemo.Vector2;
import com.example.animdemo.render.ContextParameters;
import com.example.animdemo.render.DrawableBitmap;
import com.example.animdemo.render.DrawableFactory;
import com.example.animdemo.render.RenderSystem;
import com.example.animdemo.render.Texture;

/**
 * A very simple manager for orthographic in-game UI elements.
 * TODO: This should probably manage a number of hud objects in keeping with the component-centric
 * architecture of this engine.  The current code is monolithic and should be refactored.
 */
public class HudSystem extends BaseObject {
    private static final int MAX_DIGITS = 4;

    private Texture mFadeTexture;
    private float mFadeStartTime;
    private float mFadeDuration;
    private boolean mFadeIn;
    private boolean mFading;
    
    private int mFPS;
    private Vector2 mFPSLocation;
    private int[] mFPSDigits;
    private boolean mFPSDigitsChanged;
    private boolean mShowFPS;
    
    private DrawableBitmap[] mDigitDrawables;
    private DrawableBitmap mXDrawable;
	
    
    public HudSystem() {
        super();
        mFPSLocation = new Vector2();
        mDigitDrawables = new DrawableBitmap[10];
        mFPSDigits = new int[MAX_DIGITS];
        
        reset();
    }
    
    @Override
    public void reset() {
        mFadeTexture = null;
        mFading = false;
        mFPS = 0;
        mFPSDigits[0] = 0;
        mFPSDigits[1] = -1;
        mFPSDigitsChanged = true;
        mShowFPS = false;
        for (int x = 0; x < mDigitDrawables.length; x++) {
            mDigitDrawables[x] = null;
        }
        mXDrawable = null;
    }
    
    public void setFadeTexture(Texture texture) {
        mFadeTexture = texture;
    }
    
    public void setDigitDrawables(DrawableBitmap[] digits, DrawableBitmap xMark) {
        mXDrawable = xMark;
        for (int x = 0; x < mDigitDrawables.length && x < digits.length; x++) {
            mDigitDrawables[x] = digits[x];
        }
    }
    
    
    public void startFade(boolean in, float duration) {
        mFadeStartTime = sSystemRegistry.timeSystem.getRealTime();
        mFadeDuration = duration;
        mFadeIn = in;
        mFading = true;
    }
    
    public void clearFade() {
        mFading = false;
    }
    
    public boolean isFading() {
        return mFading;
    }
    
    
    public void setFPS(int fps) {
    	mFPSDigitsChanged = (fps != mFPS);
    	mFPS = fps;
    }
    
    public void setShowFPS(boolean show) {
    	mShowFPS = show;
    }
    
    @Override
    public void update(float timeDelta, BaseObject parent) {
        final RenderSystem render = sSystemRegistry.renderSystem;
        final ContextParameters params = sSystemRegistry.contextParameters;
        final DrawableFactory factory = sSystemRegistry.drawableFactory;

        if (mShowFPS) {
        	if (mFPSDigitsChanged) {
            	int count = intToDigitArray(mFPS, mFPSDigits);
            	mFPSDigitsChanged = false;
                mFPSLocation.set(params.gameWidth - 10.0f - ((count + 1) * (mDigitDrawables[0].getWidth() / 2.0f)), 10.0f);

            }
            drawNumber(mFPSLocation, mFPSDigits, false);
        }
        
        if (mFading && factory != null) {
            
            final float time = sSystemRegistry.timeSystem.getRealTime();
            final float fadeDelta = (time - mFadeStartTime);
            
            float percentComplete = 1.0f;
            if (fadeDelta < mFadeDuration) {
                percentComplete = fadeDelta / mFadeDuration;
            } else if (mFadeIn) {
                // We've faded in.  Turn fading off.
                mFading = false;
            } 
            
            if (percentComplete < 1.0f || !mFadeIn) {
                float opacityValue = percentComplete;
                if (mFadeIn) {
                    opacityValue = 1.0f - percentComplete;
                }
                
                DrawableBitmap bitmap = factory.allocateDrawableBitmap();
                if (bitmap != null) {
                    bitmap.setWidth(params.gameWidth);
                    bitmap.setHeight(params.gameHeight);
                    bitmap.setTexture(mFadeTexture);
                    bitmap.setCrop(0, mFadeTexture.height, mFadeTexture.width, mFadeTexture.height);
                    bitmap.setOpacity(opacityValue);
                    render.scheduleForDraw(bitmap, Vector2.ZERO, SortConstants.FADE, false);
                }
            }
            
        }
    }
    
    private void drawNumber(Vector2 location, int[] digits, boolean drawX) {
        final RenderSystem render = sSystemRegistry.renderSystem;
        
        if (mDigitDrawables[0].getWidth() == 0) {
            // first time init
            for (int x = 0; x < mDigitDrawables.length; x++) {
                Texture tex = mDigitDrawables[x].getTexture();
                mDigitDrawables[x].resize(tex.width, tex.height);
            }
        }
        
        if (mXDrawable.getWidth() == 0) {
            // first time init
            Texture tex = mXDrawable.getTexture();
            mXDrawable.resize(tex.width, tex.height);
        }
        
        final float characterWidth = mDigitDrawables[0].getWidth() / 2.0f;
        float offset = 0.0f;
        
        if (mXDrawable != null && drawX) {
            render.scheduleForDraw(mXDrawable, location, SortConstants.HUD, false); 
            location.x += characterWidth;
            offset += characterWidth;
         }
        
        for (int x = 0; x < digits.length && digits[x] != -1; x++) {
            int index = digits[x];
            DrawableBitmap digit = mDigitDrawables[index];
            if (digit != null) {
                render.scheduleForDraw(digit, location, SortConstants.HUD, false);
                location.x += characterWidth;
                offset += characterWidth;
            }
        }
        
        location.x -= offset;
        
        
    }

    public int intToDigitArray(int value, int[] digits) {
    	int characterCount = 1;
        if (value >= 1000) {
            characterCount = 4;
        } else if (value >= 100) {
            characterCount = 3;
        } else if (value >= 10) {
            characterCount = 2;
        }
        
    	int remainingValue = value;
        int count = 0;
	    do {
	        int index = remainingValue != 0 ? remainingValue % 10 : 0;
	        remainingValue /= 10;
	        digits[characterCount - 1 - count] = index;
	        count++;
	    } while (remainingValue > 0 && count < digits.length);
	    
	    if (count < digits.length) {
	    	digits[count] = -1;
	    }
	    return characterCount;
    }
       
    
}
